package edu.hawaii.halealohacli.processor;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.wattdepot.client.WattDepotClient;
import edu.hawaii.halealohacli.command.Command;

/**
 * Uses a command string to load and invoke the appropriate Command class.
 * 
 * @author Leo deCandia
 */
@SuppressWarnings("rawtypes")
public class QueryProcessor {

  /** The class registry. */
  Map<String, Class> registry = new HashMap<String, Class>();
  /** The usage string dictionary. */
  Map<String, String> usageInfo = new HashMap<String, String>();
  /** The wattdepot client connection. */
  WattDepotClient client;
  
  /**
   * Instantiates a new query processor.
   *
   * @param client the client
   */
  public QueryProcessor(WattDepotClient client) {
    List<Class> classesInPackage = null;
    this.client = client;
    
    //classesInPackage = CommandFinderUtils.getClasses2();
    
    
    try {
      classesInPackage = 
          CommandFinderUtils.getClassesBothJarAndFile("edu.hawaii.halealohacli.command");
      
    }
    catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    catch (IOException e) {
      e.printStackTrace();
    }
    

    if (classesInPackage == null) {
      System.out.println("Unable to find command package");
      // throw new CommandPackageNotFoundException();
    }
    else {

      for (Class klass : classesInPackage) {
        if (!klass.isInterface() && Command.class.isAssignableFrom(klass)) {
          Command command;
          try {
            command = (Command) klass.newInstance();

            String commandSlug = command.getCommandName();
            registry.put(commandSlug, klass);
            String commandUsage = command.getCommandUsage();
            usageInfo.put(commandSlug, commandUsage);
            //System.out.println("found command " + commandSlug);
          }
          catch (InstantiationException e) {
            e.printStackTrace();
          }
          catch (IllegalAccessException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  
  /**
   * Gets the registry.
   *
   * @return the usage info dictionary
   */
  public Map<String, String> getUsageDictionary() {
    return Collections.unmodifiableMap(usageInfo);
  }
  
  /**
   * Invoke command by name.
   * 
   * @param commandString the command string
   * @param args the args to the command class
   * @return true, if successful
   */
  public boolean invokeCommandByName(String commandString, String[] args) {

    Class klass = registry.get(commandString);
    if (klass == null) {
      return false;
    }
    try {
      Command command = (Command) klass.newInstance();
      command.initialize(args, client);
      command.execute();
    }
    catch (InstantiationException e) {
      e.printStackTrace();
    }
    catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    return true;
  }

}
